package Operations;

import Data.DbData;
import Data.RuleDB;
import Enumeration.TypesResult;
import Operations.Export.AExport;
import GUI.ResultData;
import GUI.AObserver;
import java.util.ArrayList;
import java.util.Date;
import java.util.Observer;

/**
 * @author Martin
 * @version 1.0
 * @created 14-III-2012 13:12:27
 */
public abstract class AOperations {

    protected RuleDB db;
    protected ArrayList<DbData> dbData;   //sem ukladat data ziskana z db pro vypocet, je to potreba pro export
    private SimpleFactory simpleFactory;
    private ArrayList<AObserver> observers;
    protected AExport export;
    //public RuleDB m_RuleDB;
    //public AExport m_AExport;
    //public AObserver m_AObserver;

    public AOperations() {
        dbData = new ArrayList<DbData>();
        observers = new ArrayList<AObserver>();
        simpleFactory = new SimpleFactory();
        this.db = RuleDB.createInstance(this.observers);
    }

    /**
     * 
     * @param observer
     */
    public void addObeserver(AObserver observer) {
        observers.add(observer);
    }

    /**
     * vyuziva seznam ziskanych dat dbData
     */
    public abstract void export();

    /**
     * delegujeme tridu RuleDB, mozna zbytecna metoda
     * 
     * @param from
     * @param to
     */
    public void getData(Date from, Date to) {
        if (db != null) {
            db.getData(from, to);
        } else {
            update("databáze nenalezena");
        }
    }

    /**
     * 
     * @param to
     * @param from
     * @param resultData
     */
    public abstract void operationAll(Date to, Date from, ResultData resultData);

    /**
     * zadan mesic
     * 
     * @param month
     * @param resultData
     */
    public abstract void operationAll(int month, int year, ResultData resultData);

    /**
     * ze vsech dat
     * 
     * @param resultData
     */
    public abstract void operationAll(ResultData resultData);

    /**
     * 
     * @param message
     */
    public void update(String message) {
        for (AObserver obs : observers) {
            obs.messageOperation(message);
        }
    }

    protected void testGap(Date from, Date to) {
        //nasimulovat jestli skutecne funguje a potom pro spanka, at si to muze vyzkouset
        //boolean foundGap = false;
        if ((dbData != null)&&(dbData.size()>0)) 
        {                        
            ArrayList<String> gaps = new ArrayList<String>();
            
            //test díry v datech od začátku zadaného dne(čas 00:00) do první položky z databáze
            if((dbData.get(0).getDate().getTime() - from.getTime())>3600000){gaps.add(from + " - " + dbData.get(0).getDate());}
            //test díry v datech mezi položkami v databázi
            for (int i = 1; i < dbData.size() - 1; i++) {
                if ((dbData.get(i).getDate().getTime() - dbData.get(i - 1).getDate().getTime()) > 3600000) {
                    gaps.add(dbData.get(i).getDate() + " - " + dbData.get(i - 1).getDate()); //mezeru v datech napsat jeste od kdy do kdy             
                }
            }
            //test díry v datech od poslední položky z databáze do konce posledního testovaného dne (čas 23:59)
            if(to.getTime()-dbData.get(dbData.size()-1).getDate().getTime()>3600000){gaps.add(dbData.get(dbData.size()-1).getDate() + " - " + to );}
            
            if(gaps.size()>0)
            {
                StringBuilder message = new StringBuilder();
             
                if(gaps.size()==1)
                    {message.append("Nalezena mezera v datech :\n");}
                else if(gaps.size()<5)
                    {   message.append("Nalezeny ").append(gaps.size()).append(" mezery v datech :\n");}
                else
                    { message.append("Nalezeno ").append(gaps.size()).append(" mezer v datech :\n");}
                
                for(int i=0;i<gaps.size();i++)
                    {message.append(gaps.get(i)).append("\n");}
                
                update(message.toString());
            }
        }       
    }
    
    public void makeOperation(ResultData resultData)
    {
        if(dbData.size()>0){   
            simpleFactory.createOperation(dbData, resultData, TypesResult.all); 
        }else{
            update("Žádná data pro požadované období nejsou k dispozici");
            //ideálním řešením by podle mě bylo nastavit resultData=null a potom je v subjectu kontrolovat, místo nastavení průměru na -1
            //ale funkci to plní stejně dobře a předávat promněnný byRef sem se dočetl že nejde a přišlo mi zbytečný dělat další metodu typu resultData.areFilled()
            resultData.setAverage(-1);                    
        }
    }
}